/************************************************************************************************/
/*Lab 3: AssemblerClasses.cpp									*/
/*												*/
/*Description: This c file defines the commands for the "AssemblerData", the "AssemblyCommands",*/
/*	       and the "Comments" classes.							*/
/*												*/
/*Modification Log:										*/
/*												*/
/*		2012/07/07 - Adjusted the "General" class and the "AssemblyCommands" class to	*/
/*			     not need destructors and made them store just a plain vector or	*/
/*			     string instead of a pointer to one.  Also created special return	*/
/*			     funtions to make accessing much easier then it was before. The	*/
/*			     section with these commands is called "Special Return Commands" and*/
/*			     will make it easier to access information deep in the classes.	*/
/*			     (Samuel Thacker)							*/
/*		2012/03/05 - Defined bool "err_empty()" command for the "AssemblerData" class.	*/
/*			     (Samuel Thacker)							*/
/*		2012/02/28 - Updated this file to be compatable with the header file.		*/
/*			     (Samuel Thacker)							*/
/*		2012/02/15 - Created Append commands for "AssemblyCommands" for the "comments",	*/
/*			     "mc_data", and "errors" vectors. (Samuel Thacker)			*/
/*		2012/02/14 - Created Return commands for "AssemblyCommands".  Modified all 	*/
/*			     string return commands to return a string instead of a pointer.	*/
/*			     Created the Constructor, the Destructor, and the Return commands	*/
/*			     for the "Comments" class and the "Errors" class. (Samuel Thacker)	*/
/*		2012/02/13 - Created the Constructor, the Destructor, and the Return commands	*/
/*			     for the "AssemblerData" class.  Created the constructors and the	*/
/*			     destructor for the "AssemblyCommands" class. (Samuel Thacker)	*/ 
/*		2012/02/10 - Creation of this header file. (Samuel Thacker)			*/
/*												*/
/*               ----Please report any modifications made to this file please----               */
/************************************************************************************************/

#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include "AssemblerClasses.h"

using namespace std;

/*****************/
/* AssemblerData */
/*****************/

/* Constructor and Destructor */
AssemblerData::AssemblerData() //Constructor
	{
	data = new vector<AssemblyCommands>;
	directives = new vector<AssemblyCommands>;
	labels = new vector<General>;
	comments = new vector<General>;
	mc_data = new vector<unsigned int>;
	errors = new vector<string>;
	} //END AssemblerData()

AssemblerData::~AssemblerData() //Destructor
	{
	delete data;
	delete directives;
	delete labels;
	delete comments;
	delete mc_data;
	delete errors;
	} //END ~AssemblerData()

/* Return Commands */
vector<AssemblyCommands> * AssemblerData::ret_data() //Returns "data" (pointer).
	{
	return data;
	} //END ret_data()

vector<AssemblyCommands> * AssemblerData::ret_dir() //Returns "directives" (pointer).
	{
	return directives;
	} //END ret_dir()

vector<General> * AssemblerData::ret_lab() //Returns "comments" (pointer).
	{
	return labels;
	} //END ret_lab()

vector<General> * AssemblerData::ret_com() //Returns "comments" (pointer).
	{
	return comments;
	} //END ret_com()

vector<unsigned int> * AssemblerData::ret_mcData() //Returns "mc_data" (pointer).
	{
	return mc_data;
	} //END ret_mcData()

vector<string> * AssemblerData::ret_err() //Returns "errors" (pointer).
	{
	return errors;
	} //END ret_mcData()

/* Length Commands */
unsigned int AssemblerData::data_len() //Returns the number of elements in "data"
	{
	return (*data).size();
	} //END data_len()

unsigned int AssemblerData::dir_len() //Returns the number of elements in "directives"
	{
	return (*directives).size();
	} //END dir_len()

unsigned int AssemblerData::lab_len() //Returns the number of elements in "labels"
	{
	return (*labels).size();
	} //END lab_len()

unsigned int AssemblerData::com_len() //Returns the number of elements in "comments"
	{
	return (*comments).size();
	} //END com_len()

unsigned int AssemblerData::mcData_len() //Returns the number of elements in "mc_data"
	{
	return (*mc_data).size();
	} //END mcData_len()

unsigned int AssemblerData::err_len() //Returns the number of elements in "errors"
	{
	return (*errors).size();
	} //END err_len()

/* Special Return Commands */

// Data //
vector<string> AssemblerData::ret_data(unsigned int i) //Returns the "code" vector stored at index position "i"
	{
	if (i+1 > (*data).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 1: invalid access (i) for function \"ret_data(unsigned int i)\".\n";
		exit(1);
		}
	return (*data)[i].ret_code();
	} //END ret_data(unsigned int i)

string AssemblerData::ret_data(unsigned int i, unsigned int j) //Returns the "code" stored at index position "j" of (*data)[i]
	{
	if (i+1 > (*data).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 2: invalid access (i) for function \"ret_data(unsigned int i,unsigned int i)\".\n";
		exit(2);
		}
	if (j+1 > (((*data)[i]).ret_code()).size())
		{ //Returns an error if j goes out of bounds.
		cout << "Error 3: invalid access (j) for function \"ret_data(unsigned int i,unsigned int i)\".\n";
		exit(3);
		}
	return ((*data)[i].ret_code())[j];
	} //END ret_data(unsigned int i,unsigned int j)

unsigned int AssemblerData::ret_dataLN(unsigned int i) //Returns the line number stored at index position "i"
	{
	if (i+1 > (*data).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 4: invalid access (i) for function \"ret_dataLN(unsigned int i)\".\n";
		exit(4);
		}
	return (*data)[i].ret_ln();
	} //END ret_dataLN(unsigned int i)

string AssemblerData::ret_dataFN(unsigned int i) //Returns the file name stored at index position "i"
	{
	if (i+1 > (*data).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 5: invalid access (i) for function \"ret_dataFN(unsigned int i)\".\n";
		exit(5);
		}
	return (*data)[i].ret_fname();
	} //END ret_dataFN(unsigned int i)

// Directives //
vector<string> AssemblerData::ret_dir(unsigned int i) //Returns the "code" vector stored at index position "i"
	{
	if (i+1 > (*directives).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 6: invalid access (i) for function \"ret_dir(unsigned int i)\".\n";
		exit(6);
		}
	return (*directives)[i].ret_code();
	} //END ret_dir(unsigned int i)

string AssemblerData::ret_dir(unsigned int i, unsigned int j) //Returns the "code" stored at index position "j" of (*directives)[i]
	{
	if (i+1 > (*directives).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 7: invalid access (i) for function \"ret_dir(unsigned int i,unsigned int i)\".\n";
		exit(7);
		}
	if (j+1 > (((*directives)[i]).ret_code()).size())
		{ //Returns an error if j goes out of bounds.
		cout << "Error 8: invalid access (j) for function \"ret_dir(unsigned int i,unsigned int i)\".\n";
		exit(8);
		}
	return ((*directives)[i].ret_code())[j];
	} //END ret_dir(unsigned int i,unsigned int j)

unsigned int AssemblerData::ret_dirLN(unsigned int i) //Returns the line number stored at index position "i"
	{
	if (i+1 > (*directives).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 9: invalid access (i) for function \"ret_dirLN(unsigned int i)\".\n";
		exit(9);
		}
	return (*directives)[i].ret_ln();
	} //END ret_dirLN(unsigned int i)

string AssemblerData::ret_dirFN(unsigned int i) //Returns the file name stored at index position "i"
	{
	if (i+1 > (*directives).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 10: invalid access (i) for function \"ret_dirFN(unsigned int i)\".\n";
		exit(10);
		}
	return (*directives)[i].ret_fname();
	} //END ret_dirFN(unsigned int i)

// Labels //
string AssemblerData::ret_lab(unsigned int i) //Returns the label stored at index position "i"
	{
	if (i+1 > (*labels).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 11: invalid access (i) for function \"ret_lab(unsigned int i)\".\n";
		exit(11);
		}
	return (*labels)[i].ret_gen();
	} //END ret_lab(unsigned int i)

unsigned int AssemblerData::ret_labLN(unsigned int i) //Returns the line number stored at index position "i"
	{
	if (i+1 > (*labels).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 12: invalid access (i) for function \"ret_labLN(unsigned int i)\".\n";
		exit(12);
		}
	return (*labels)[i].ret_ln();
	} //END ret_labLN(unsigned int i)

string AssemblerData::ret_labFN(unsigned int i) //Returns the file name stored at index position "i"
	{
	if (i+1 > (*labels).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 13: invalid access (i) for function \"ret_labLN(unsigned int i)\".\n";
		exit(13);
		}
	return (*labels)[i].ret_fname();
	} //END ret_labFN(unsigned int i)

// Comments //
string AssemblerData::ret_com(unsigned int i) //Returns the label stored at index position "i"
	{
	if (i+1 > (*comments).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 14: invalid access (i) for function \"ret_com(unsigned int i)\".\n";
		exit(14);
		}
	return (*comments)[i].ret_gen();
	} //END ret_com(unsigned int i)

unsigned int AssemblerData::ret_comLN(unsigned int i) //Returns the line number stored at index position "i"
	{
	if (i+1 > (*comments).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 15: invalid access (i) for function \"ret_comLN(unsigned int i)\".\n";
		exit(15);
		}
	return (*comments)[i].ret_ln();
	} //END ret_comLN(unsigned int i)

string AssemblerData::ret_comFN(unsigned int i) //Returns the file name stored at index position "i"
	{
	if (i+1 > (*comments).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 16: invalid access (i) for function \"ret_comFN(unsigned int i)\".\n";
		exit(16);
		}
	return (*comments)[i].ret_fname();
	} //END ret_comFN(unsigned int i)

// MC Data //
unsigned int AssemblerData::ret_mcData(unsigned int i) //Returns the code stored at index position "i"
	{
	if (i+1 > (*mc_data).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 17: invalid access (i) for function \"ret_mcData(unsigned int i)\".\n";
		exit(17);
		}
	return (*mc_data)[i];
	} //END ret_mcData(unsigned int i)

// Errors //
string AssemblerData::ret_err(unsigned int i) //Returns the error stored at index position "i"
	{
	if (i+1 > (*errors).size())
		{ //Returns an error if i goes out of bounds.
		cout << "Error 18: invalid access (i) for function \"ret_err(unsigned int i)\".\n";
		exit(18);
		}
	return (*errors)[i];
	} //END ret_err(unsigned int i)

/* Append Commands */
void AssemblerData::data_append(vector<string> DATA,unsigned int LN,string FNAME) //Appends a list of tokens to "data"
	{
	(*data).push_back(AssemblyCommands(DATA,LN,FNAME));
	} //END data_append(vector<string> DATA,unsigned int LN,string FNAME)

void AssemblerData::dir_append(vector<string> DIR,unsigned int LN,string FNAME) //Appends a list of tokens to "directives"
	{
	(*directives).push_back(AssemblyCommands(DIR,LN,FNAME));
	} //END dir_append(vector<string> DIR,unsigned int LN,string FNAME)

void AssemblerData::lab_append(string LAB,unsigned int LN,string FNAME) //Appends a label to "labels"
	{
	(*labels).push_back(General(LAB,LN,FNAME));
	} //END lab_append(string COM,unsigned int LN,string FNAME)

void AssemblerData::com_append(string COM,unsigned int LN,string FNAME) //Appends a comment to "comments"
	{
	(*comments).push_back(General(COM,LN,FNAME));
	} //END com_append(string COM,unsigned int LN,string FNAME)

void AssemblerData::mcData_append(unsigned int MachineCode) //Appends machine code (integer) to "mc_data"
	{
	(*mc_data).push_back(MachineCode);
	} //END mcData_append(unsigned int MachineCode)

void AssemblerData::err_append(string ERR) //Appends a comment to "comments"
	{
	(*errors).push_back(ERR);
	} //END err_append(string ERR)

/* Special Commands */
bool AssemblerData::err_empty() //Checks if vector "error" is empty. 1 if it is and 0 if otherwise.
	{
	return (*errors).empty();
	} //END err_empty();

/* END AssemblerData */


/********************/
/* AssemblyCommands */
/********************/

/* Constructor and Destructor */

/* Constructor */
AssemblyCommands::AssemblyCommands(vector<string> CODE,unsigned int LN,string FNAME)
	{
	/* Strings */
	code = CODE;
	fname = FNAME;

	/* Line Number */
	ln = LN;
	
	} //END AssemblyCommands(string ODL, string REG_1, string REG_2, string REG_3, unsigned int LN)

/* Return Commands */
vector<string> AssemblyCommands::ret_code() //returns "code"
	{
	return code;
	} //END ret_code()

unsigned int AssemblyCommands::ret_ln() //returns "ln"
	{
	return ln;
	} //END ret_ln()

string AssemblyCommands::ret_fname() //returns "fname"
	{
	return fname;
	} //END ret_ln()

/* END AssemblyCommands */


/***********/
/* General */
/***********/

/* Constructor and Destructor */
General::General(string GEN, unsigned int LN,string FNAME) //Constructor
	{
	gen = GEN; //Copies string "GEN" and assigns it to allocated "gen"
	fname = FNAME; //Copies string "FNAME" and assigns it to allocated "fname"
	ln = LN; //Assigns the value of "LN" to "ln" (line number).
	} //END Comments(string COM, unsigned int LN)

/* Return Commands */
string General::ret_gen() //returns "gen"
	{
	return gen;
	} //END ret_gen()

unsigned int General::ret_ln() //returns "ln"
	{
	return ln;
	} //END ret_ln()

string General::ret_fname() //returns "fname"
	{
	return fname;
	} //END ret_fname()

/* END General */

/* EOF AssemblerClasses.cpp */
